/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * File Name          : freertos.c
  * Description        : Code for freertos applications
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "lcd.h"
#include "keyled.h"
#include "event_groups.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define BITMASK_LED0	0x01
#define BITMASK_LED1	0x02
#define BITMASK_LED2	0x04
#define BITMASK_SYNC	BITMASK_LED0|BITMASK_LED1|BITMASK_LED2
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */

/* USER CODE END Variables */
/* Definitions for Task_LED0 */
osThreadId_t Task_LED0Handle;
const osThreadAttr_t Task_LED0_attributes = {
  .name = "Task_LED0",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for Task_LED1 */
osThreadId_t Task_LED1Handle;
const osThreadAttr_t Task_LED1_attributes = {
  .name = "Task_LED1",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for Task_LED2 */
osThreadId_t Task_LED2Handle;
const osThreadAttr_t Task_LED2_attributes = {
  .name = "Task_LED2",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for Event_Sync */
osEventFlagsId_t Event_SyncHandle;
const osEventFlagsAttr_t Event_Sync_attributes = {
  .name = "Event_Sync"
};

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */

/* USER CODE END FunctionPrototypes */

void AppTask_LED0(void *argument);
void AppTask_LED1(void *argument);
void AppTask_LED2(void *argument);

void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/**
  * @brief  FreeRTOS initialization
  * @param  None
  * @retval None
  */
void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* creation of Task_LED0 */
  Task_LED0Handle = osThreadNew(AppTask_LED0, NULL, &Task_LED0_attributes);

  /* creation of Task_LED1 */
  Task_LED1Handle = osThreadNew(AppTask_LED1, NULL, &Task_LED1_attributes);

  /* creation of Task_LED2 */
  Task_LED2Handle = osThreadNew(AppTask_LED2, NULL, &Task_LED2_attributes);

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
  /* USER CODE END RTOS_THREADS */

  /* Create the event(s) */
  /* creation of Event_Sync */
  Event_SyncHandle = osEventFlagsNew(&Event_Sync_attributes);

  /* USER CODE BEGIN RTOS_EVENTS */
  /* add events, ... */
  /* USER CODE END RTOS_EVENTS */

}

/* USER CODE BEGIN Header_AppTask_LED0 */
/**
  * @brief  Function implementing the Task_LED0 thread.
  * @param  argument: Not used
  * @retval None
  */
/* USER CODE END Header_AppTask_LED0 */
void AppTask_LED0(void *argument)
{
  /* USER CODE BEGIN AppTask_LED0 */
  /* Infinite loop */
  for(;;)
  {
	KEYS curkey=ScanPressedKey(50);
	if(curkey != KEY0)
	{
		vTaskDelay(pdMS_TO_TICKS(50));
		continue;
	}
	LCD_ShowStr(10, LCD_CurY+LCD_SP20, "Task_LED0 reaches sync point");
	xEventGroupSync(Event_SyncHandle, BITMASK_LED0, BITMASK_SYNC, portMAX_DELAY);
	while(1)
	{
		LED0_Toggle();
		vTaskDelay(pdMS_TO_TICKS(300));
	}
}
  /* USER CODE END AppTask_LED0 */
}

/* USER CODE BEGIN Header_AppTask_LED1 */
/**
* @brief Function implementing the Task_LED1 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_AppTask_LED1 */
void AppTask_LED1(void *argument)
{
  /* USER CODE BEGIN AppTask_LED1 */
	/* Infinite loop */
	for(;;)
	{
		KEYS curkey=ScanPressedKey(50);
		if(curkey != KEY1)
		{
			vTaskDelay(pdMS_TO_TICKS(50));
			continue;
		}
		LCD_ShowStr(10, LCD_CurY+LCD_SP20, "Task_LED1 reaches sync point");
		xEventGroupSync(Event_SyncHandle, BITMASK_LED1, BITMASK_SYNC, portMAX_DELAY);
		while(1)
		{
			LED1_Toggle();
			vTaskDelay(pdMS_TO_TICKS(500));
		}
 	}
  /* USER CODE END AppTask_LED1 */
}

/* USER CODE BEGIN Header_AppTask_LED2 */
/**
* @brief Function implementing the Task_LED2 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_AppTask_LED2 */
void AppTask_LED2(void *argument)
{
  /* USER CODE BEGIN AppTask_LED2 */
	 /* Infinite loop */
	  for(;;)
	  {
		  KEYS curkey=ScanPressedKey(50);
	    if(curkey != KEY2)
	    {
	    	vTaskDelay(pdMS_TO_TICKS(50));
	    	continue;
	    }
	    LCD_ShowStr(10, LCD_CurY+LCD_SP20, "Task_LED2 reaches sync point");
	    xEventGroupSync(Event_SyncHandle, BITMASK_LED2, BITMASK_SYNC, portMAX_DELAY);
	    while(1)
	    {
	    	LED2_Toggle();
	    	vTaskDelay(pdMS_TO_TICKS(600));
	    }
	  }
  /* USER CODE END AppTask_LED2 */
}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */

/* USER CODE END Application */

